home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1995 November
/
EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso
/
earcd
/
util
/
misc
/
browseri.lha
/
BrowserII_v3_09
/
Sources
/
For.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-11-09
|
21KB
|
747 lines
/*
* Copyright © 1992-94 by S.R. & P.C.
*
* Created: 30 Mar 1992 18:26:36
* Modified: 09 Nov 1994 23:11:45
*
* Make>> rx BumpRev For 3 8
* Make>> sc <file>.c
* Make>> slink LIB:cs.o <file>.o SC SD BATCH NOICONS TO <file> LIB LIB:c.lib
* Make>> protect <file> P ADD
*
*
* 30/03/1992: V1.0 (Pierre Carrette)
* Simple version with template: "Args/M,ALL/S,DONTFAIL/S,DO/K/A/F"
* 4/07/1994: V2.2 (Sylvain Rougier)
* No longer add the name of the object if no '%%' present
* 5/07/1994: V3.0
* Add the 'Quiet' option not to print hierarchy (but still print FileType if asked)
* Now work as it should always work: don't scan all the directory if no pattern
* but scan all subdir if 'All' option specified.
* Add the 'GivePathName' option to provide a Full Path arguments to the command.
* No longuer add '"' around the file name. User can type '"%%"' if he need it.
* 7/07/1994 V3.1
* If a full pathname file entry was specified, For don't find it type. fixed
* 15/07/1994 V3.2
* Guru if a single file was suplied. fixed
* Now FullPathArgs realy work
* Don't put optimize or it guru ! (see note)
* 31/07/1994 V3.3
* Check the stack size because it need at least 8192 (probably !...)
* put optimize again. just to see.
* 07/08/1994 V3.4
* Remove optimize because the sasc bug still here
* correct some error int the doc ( the '*' was incorrectly used instead of the '"')
* 21/08/1994 V3.5
* Now use StackSwap() to avoid stack pb
* 22/09/1994 V3.6 (Pierre Carrette is back :-)
* Major code cleanup. No more need StackSwap(). Bug fixes in template. whatis.library now Optional.
* Inverted 'Quiet' to 'Verbose'. Changed 'VNFileType' to more comprehensive 'FileTypeVar' keyword.
* Changed 'GivePathName' to 'FullPathArgs'.
* FileTypeVar was not set if Showbytes was off.
* Showbytes/ShowFileType is now off if no Cmd supplied.
* 'Type' argument syntax simplified. now: "#text,!source c"
* MatchFileType() bug fix. "#text,!source c" was not working!!
* SAS Optimisation now works!!!
* 22/09/1994 V3.7
* Recompiled with new version of c.lib which had a bug for 'ENV:' var parsing
* 09/11/1994 V3.8
* Bug fix. File UnLock()ed before processed so that command can open it for writing.
*/
#include <clib.h>
#include <libraries/WhatIsBase.h>
#include <proto/WhatIs.h>
#include "For_rev.h"
// Startup Modules...
CliArgs; ReadEnvArgs("For");
static char Version[] = VERSTAG;
STRPTR Template = "\
Pattern/A/M,Files/K,Dirs/K,Since/K,Before/K,MinSize/K/N,MaxSize/K/N,\
PosProtect/K,NegProtect/K,Type/K,All/S,ASync/S,ReadSize/K/N,ShowBytes/K/N,\
D=Deep/K/N,SFT=ShowFileType/S,FTV=FileTypeVar/K,FPA=FullPathArgs/S,Verbose/S,Do/K/F";
STRPTR CliHelp = VERS" ("DATE")
© Sylvain Rougier & Pierre Carrette.
\n\
Usage: For <Pattern> [Files <MATCH|YES|NO>] [Dirs <MATCH|YES|NO>]\n\
[Since <Date>] [Before <Date>] [MinSize <Number>] [MaxSize <Number>]\n\
[PosProtect <L|C|H|S|P|A|R|W|E|D>] [NegProtect <L|C|H|S|P|A|R|W|E|D>]\n\
[Type <[#=SUB,~=EXLC]FileType0,,,FileType15>] [All] [ASync] [ReadSize]\n\
[ShowBytes] [Deep] [ShowFileType] [FileTypeVar <var name>] [FullPathArgs]\n\
[DO <Command [args] [,Command [args] [,...]]>]\n";
#define ARG_Template 0
#define ARG_Files 1
#define ARG_Dirs 2
#define ARG_Since 3
#define ARG_Before 4
#define ARG_MinSize 5
#define ARG_MaxSize 6
#define ARG_PosProtect 7
#define ARG_NegProtect 8
#define ARG_Type 9
#define ARG_ALL 10
#define ARG_ASYNC 11
#define ARG_READSIZE 12
#define ARG_SHOWBYTES 13
#define ARG_DEEPWHATIS 14
#define ARG_SHOWFILETYPE 15
#define ARG_FileTypeVar 16
#define ARG_FullPathArgs 17
#define ARG_Verbose 18
#define ARG_CMD 19
#define ARG_ENDARG 20
struct Library *WhatIsBase;
#define MAX_PATHLEN 256
#define MAX_CMDLEN 512
/* char used in the filetype spec string */
#define NOTFileType '~'
#define WITHSubTypes '#'
/*******************************************************/
/* not in dos.h !! */
#define FIBB_HOLD 7
#define FIBF_HOLD (1<<FIBB_HOLD)
/* it is my own definition: not standard */
#define FIBB_COMMENT 8
#define FIBF_COMMENT (1<<FIBB_COMMENT)
#define FIBB_LINK 9
#define FIBF_LINK (1<<FIBB_LINK)
#define PATTERN_BUF_SIZE 40
#define MAX_FTS 16 /* Max FileTypeSpec in SelectInfo */
struct FileTypeSpec {
FileType fs_FileType;
UWORD fs_Flags;
};
/* FileTypeSpec flags */
#define FTSF_EXCLUDETYPE 0x0001 /* Exclude this type (otherwise include) */
#define FTSF_WITHSUBTYPES 0x0002 /* Affect Include/Exclude to subtypes */
struct SelectInfo {
UBYTE si_PatTok[PATTERN_BUF_SIZE]; /* PreParsed pattern */
LONG si_MinSize; /* Show files bigger than that */
LONG si_MaxSize; /* and smaller than that */
struct DateStamp si_SinceDate; /* Show files newer than that */
struct DateStamp si_BeforeDate; /* and older than that */
UWORD si_PosProtect; /* Show files that have these bits set */
UWORD si_NegProtect; /* Show files that have these bits clear */
struct FileTypeSpec si_FileTypes[MAX_FTS]; /* Include and Exclude file types */
UWORD si_NumFts; /* Number of FileTypeSpec in previous array */
UWORD si_Flags; /* Flags. See below */
};
/* SelectInfo flags */
#define SI_ALL_FILES 0x0001
#define SI_MATCH_FILES 0x0002
#define SI_ALL_DIRS 0x0004
#define SI_MATCH_DIRS 0x0008
#define SI_AFFECT_SUBDIRS 0x0010
#define SI_NAME 0x0020
#define SI_SIZE 0x0040
#define SI_SINCEDATE 0x0080
#define SI_BEFOREDATE 0x0100
#define SI_POSPROTECTION 0x0200
#define SI_NEGPROTECTION 0x0400
#define SI_POSFILETYPE 0x0800
#define SI_NEGFILETYPE 0x1000
#define SI_FILETYPE (SI_POSFILETYPE|SI_NEGFILETYPE)
#define SI_MATCHBITS (SI_NAME|SI_SIZE|SI_SINCEDATE|SI_BEFOREDATE|SI_POSPROTECTION|SI_NEGPROTECTION|SI_FILETYPE)
struct Opt {
BOOL Verbose; /* Print some information */
BOOL Async; /* Run commands Asynchronously */
BOOL FullPathArgs; /* Give Full PathName in Fmt ? */
BOOL ShowFileType; /* Show FileType ? */
LONG ReadSize; /* Size to read to find filetype */
ULONG Deep; /* deep level to find FileType */
UWORD Showbytes; /* number of bytes to show */
STRPTR FileTypeVar; /* Name of FileType var. no var if null */
};
/* return pointer to the first non blank char in a string, or to the '\0' if the string is empty */
static char *FirstNonBlank(char *buf)
{
while (*buf && *buf == ' ')
buf++;
return buf;
}
/* check if buffer is empty or not */
static BOOL IsEmpty(char *buf)
{
return (BOOL) ((*FirstNonBlank(buf)) ? FALSE : TRUE);
}
static BOOL String2Date(char *src, struct DateStamp *ds)
{
struct DateTime *dt;
BOOL Ok = TRUE;
char *s1, *s2;
char buf[60];
if (!(dt = AllocMem(sizeof(struct DateTime), MEMF_PUBLIC | MEMF_CLEAR)))
return FALSE;
strcpy(buf, src);
s1 = s2 = FirstNonBlank(buf);
if (*s1) {
dt->dat_StrDate = s1;
while (*s2 && *s2 != ' ')
s2++;
if (*s2) {
*s2++ = '\0';
s2 = FirstNonBlank(s2);
}
if (*s2) {
dt->dat_StrTime = s2;
if (!StrToDate(dt))
Ok = FALSE;
}
else if (!StrToDate(dt)) {
dt->dat_StrDate = NULL;
dt->dat_StrTime = s1;
if (!StrToDate(dt))
Ok = FALSE;
}
if (Ok)
*ds = dt->dat_Stamp;
}
FreeMem(dt, sizeof(struct DateTime));
return Ok;
}
static void PrintByte(UBYTE Buffer[], LONG BufLen, UBYTE Num)
{
register short i;
if (BufLen > 0) {
for (i = 0; i < Num && i < BufLen; i++)
Printf("%02lx", Buffer[i]);
}
}
/*
* Parse a line that may contain comas. Backslash ('\') is the override char.
*/
static UWORD ProtectBit(char P[])
{
UWORD PB = 0;
while (*P) {
switch (*P) {
case 'L':
case 'l':
PB |= FIBF_LINK; /* another magic bit! */
break;
case 'C':
case 'c':
PB |= FIBF_COMMENT; /* our magic bit! */
break;
case 'H':
case 'h':
PB |= FIBF_HOLD;
break;
case 'S':
case 's':
PB |= FIBF_SCRIPT;
break;
case 'P':
case 'p':
PB |= FIBF_PURE;
break;
case 'A':
case 'a':
PB |= FIBF_ARCHIVE;
break;
case 'R':
case 'r':
PB |= FIBF_READ;
break;
case 'W':
case 'w':
PB |= FIBF_WRITE;
break;
case 'E':
case 'e':
PB |= FIBF_EXECUTE;
break;
case 'D':
case 'd':
PB |= FIBF_DELETE;
break;
}
P++;
}
return PB;
}
static UWORD __inline EasyProtect(LONG Protection)
{
return (UWORD) ((Protection ^ 0x0F) & 0x00FF); /* Complement 4 lower bits so all work the same way */
}
static BOOL Match(struct SelectInfo * SelectInfo, struct FileInfoBlock *fib)
{
if (fib->fib_DirEntryType < 0) { /* this is a file */
if (SelectInfo->si_Flags & SI_ALL_FILES)
return TRUE;
else if (!(SelectInfo->si_Flags & SI_MATCH_FILES))
return FALSE;
}
else { /* Dir */
if (SelectInfo->si_Flags & SI_ALL_DIRS)
return TRUE;
else if (!(SelectInfo->si_Flags & SI_MATCH_DIRS))
return FALSE;
}
if (SelectInfo->si_Flags & SI_NAME) {
if (!MatchPatternNoCase(SelectInfo->si_PatTok, fib->fib_FileName))
return FALSE;
}
if (SelectInfo->si_Flags & SI_SINCEDATE) {
if (CompareDates(&SelectInfo->si_SinceDate, &fib->fib_Date) < 0)
return FALSE;
}
if (SelectInfo->si_Flags & SI_BEFOREDATE) {
if (CompareDates(&SelectInfo->si_BeforeDate, &fib->fib_Date) > 0)
return FALSE;
}
if (fib->fib_Size < SelectInfo->si_MinSize)
return FALSE;
if (SelectInfo->si_MaxSize && (fib->fib_Size > SelectInfo->si_MaxSize))
return FALSE;
{
UWORD Protection = EasyProtect(fib->fib_Protection);
if (SelectInfo->si_Flags & SI_POSPROTECTION) {
if (!(Protection & SelectInfo->si_PosProtect))
return FALSE;
}
if (SelectInfo->si_Flags & SI_NEGPROTECTION) {
if ((Protection & SelectInfo->si_NegProtect))
return FALSE;
}
}
return TRUE;
}
static BOOL MatchFileType(struct SelectInfo *SelectInfo, struct FileInfoBlock *fib, FileType Type)
{
if (WhatIsBase && (SelectInfo->si_Flags & SI_FILETYPE)) {
BOOL Sub = FALSE;
UWORD Flags, i;
do {
for( i=0 ; i<SelectInfo->si_NumFts ; i++ ) {
Flags = SelectInfo->si_FileTypes[i].fs_Flags;
if ((!Sub || (Flags & FTSF_WITHSUBTYPES)) && !CmpFileType(SelectInfo->si_FileTypes[i].fs_FileType, Type))
return (BOOL)((Flags & FTSF_EXCLUDETYPE) ? FALSE : TRUE);
}
Sub = TRUE;
} while (Type = ParentFileType(Type));
if (SelectInfo->si_Flags & SI_POSFILETYPE)
return FALSE; /* no match within include FileTypes, exclude file */
else
return TRUE; /* Only exclude types, and not found in them, include file */
}
return TRUE;
}
/*
* Parse a line that may contain comas ','. Backslash ('\') is the override
* char. This function replace comas by cariage returns so that SystemTags()
* takes them as different command lines, just like a script file.
*/
static void ParseCmdLine(char *cmd)
{
char *s, *d, c;
s = d = cmd;
while (c = *d++ = *s++) {
if (c == '\\')
*(d - 1) = *s++;
else if (c == ',')
*(d - 1) = '\n';
}
}
/* Replaces %% by %s, suitable for SPrintf() */
static void MakeFmt(char *CmdFmt, char *Cmd)
{
char *s;
strcpy(CmdFmt, Cmd);
ParseCmdLine(CmdFmt); /* Replace , by \n to separate commands */
s = CmdFmt;
while (*s) {
if (*s == '%' && *(s + 1) == '%')
*(s + 1) = 's';
s++;
}
}
static LONG ExecuteCmd(char *Cmd, STRPTR StartPath, char *Name, struct Opt *Opt)
{
char *CmdBuf, *CmdFmt, *NameBuf;
LONG rc = 20;
BOOL NoMem = TRUE;
if (CmdBuf = AllocVec(MAX_CMDLEN, MEMF_ANY)) {
if (NameBuf = AllocVec(MAX_CMDLEN, MEMF_ANY)) {
if (CmdFmt = AllocVec(MAX_CMDLEN, MEMF_ANY)) {
MakeFmt(CmdFmt, Cmd);
if (Opt->FullPathArgs) {
strcpy(NameBuf, StartPath);
AddPart(NameBuf, Name, MAX_CMDLEN);
}
else
strcpy(NameBuf, Name);
/* Allow 5 %% in cmd */
SPrintf(CmdBuf, CmdFmt, NameBuf, NameBuf, NameBuf, NameBuf, NameBuf); /* build command line */
if (Opt->Async) {
SystemTags(CmdBuf, SYS_Input, Open("*", MODE_OLDFILE),
SYS_Output, NULL, // System() will open it
SYS_Asynch, TRUE,
SYS_UserShell, TRUE,
TAG_DONE);
rc = 0;
}
else
rc = SystemTags(CmdBuf, SYS_UserShell, TRUE, TAG_DONE);
NoMem = FALSE;
FreeVec(CmdFmt);
}
FreeVec(NameBuf);
}
FreeVec(CmdBuf);
}
if (NoMem)
PrintFault(ERROR_NO_FREE_STORE, "For");
else if (rc)
PrintFault(IoErr(), "For");
return rc;
}
static LONG ProcessEntry(struct SelectInfo *SelectInfo, struct FileInfoBlock *fib, STRPTR StartPath,
STRPTR Name, UBYTE *FileData, struct Opt *Opt, STRPTR Cmd)
{
LONG RC = 0, BytesRead = 0;
FileType Type = TYPE_UNSCANNED;
if (WhatIsBase) {
if (Opt->Deep && fib->fib_DirEntryType <= 0) {
BPTR FH;
if (FH = Open(Name, MODE_OLDFILE)) {
BytesRead = Read(FH, FileData, Opt->ReadSize);
FileData[BytesRead] = '\0'; /* whatis.library need that */
Type = WhatIsTags(Name, WI_Deep, Opt->Deep, WI_FIB, fib, WI_Buffer, FileData, WI_BufLen, BytesRead, TAG_DONE);
Close(FH);
}
}
else
Type = WhatIsTags(Name, WI_Deep, LIGHTTYPE, WI_FIB, fib, TAG_DONE);
}
if (MatchFileType(SelectInfo, fib, Type)) {
if (WhatIsBase) {
STRPTR IDString;
BOOL CR = FALSE;
IDString = GetIDString(Type);
if (Opt->ShowFileType) {
Printf("%-12s %-32s", IDString, (Opt->Verbose) ? fib->fib_FileName : Name);
CR = TRUE;
}
if (Opt->Showbytes && fib->fib_DirEntryType <= 0) {
PrintByte(FileData, BytesRead, Opt->Showbytes);
CR = TRUE;
}
if (CR)
PutStr("\n");
if (Opt->FileTypeVar)
SetVar(Opt->FileTypeVar, IDString, -1L, GVF_LOCAL_ONLY);
}
if (Cmd)
RC = ExecuteCmd(Cmd, StartPath, Name, Opt);
}
return RC;
}
static LONG ProcessEntryPattern(struct AnchorPath *AP, struct SelectInfo *SelectInfo, struct Opt *Opt,
STRPTR StartPath, STRPTR Pattern, UBYTE *FileData, STRPTR Cmd)
{
BOOL DoIt = TRUE;
LONG RC=0, MatchErr;
for (MatchErr = MatchFirst(Pattern, AP); RC == 0 && MatchErr == 0; MatchErr = MatchNext(AP)) {
if (AP->ap_Flags & APF_DIDDIR) {
if (Opt->Verbose)
Printf("
%s
\n", AP->ap_Buf);
DoIt = FALSE; /* Dir processed before entering it, don't process it twice */
AP->ap_Flags &= ~APF_DIDDIR; /* clear the completed directory flag */
}
else if (AP->ap_Info.fib_DirEntryType > 0) {
if (SelectInfo->si_Flags & SI_AFFECT_SUBDIRS) {
if (Opt->Verbose)
Printf("
%s
\n", AP->ap_Buf);
AP->ap_Flags |= APF_DODIR; /* make Matchext() enter the directory */
}
else
AP->ap_Flags &= ~APF_DODIR; /* RESET this bit after MatchFirst/MatchNext to AVOID entering a dir. */
}
/* Here is code for handling each particular file */
if (DoIt && Match(SelectInfo, &AP->ap_Info))
RC = ProcessEntry(SelectInfo, &AP->ap_Info, StartPath, AP->ap_Buf, FileData, Opt, Cmd);
DoIt = TRUE;
}
MatchEnd(AP);
if (MatchErr != ERROR_NO_MORE_ENTRIES)
PrintFault(MatchErr, "For");
return RC;
}
LONG Main(char *ArgV[], struct WBStartup *WBenchMsg)
{
LONG rc = RETURN_OK;
char *StartPath = NULL, *Buffer = NULL;
struct FileInfoBlock *fib = NULL;
struct SelectInfo SelectInfo;
struct Opt Opt;
UBYTE *FileData;
WhatIsBase = OpenLibrary("whatis.library", 3L);
memset(&SelectInfo, 0, sizeof(SelectInfo));
memset(&Opt, 0, sizeof(struct Opt));
if (ArgV[ARG_Files]) {
if (!Stricmp(ArgV[ARG_Files], "MATCH"))
SelectInfo.si_Flags |= SI_MATCH_FILES;
else if (!Stricmp(ArgV[ARG_Files], "YES"))
SelectInfo.si_Flags |= SI_ALL_FILES;
}
else /* set default */
SelectInfo.si_Flags |= SI_MATCH_FILES;
if (ArgV[ARG_Dirs]) {
if (!Stricmp(ArgV[ARG_Dirs], "MATCH"))
SelectInfo.si_Flags |= SI_MATCH_DIRS;
else if (!Stricmp(ArgV[ARG_Dirs], "YES"))
SelectInfo.si_Flags |= SI_ALL_DIRS;
}
else /* set default */
SelectInfo.si_Flags |= SI_MATCH_DIRS;
if (ArgV[ARG_Since]) {
struct DateStamp DateStamp;
String2Date(ArgV[ARG_Since], &DateStamp);
SelectInfo.si_SinceDate = DateStamp;
SelectInfo.si_Flags |= SI_SINCEDATE;
}
if (ArgV[ARG_Before]) {
struct DateStamp DateStamp;
String2Date(ArgV[ARG_Before], &DateStamp);
SelectInfo.si_BeforeDate = DateStamp;
SelectInfo.si_Flags |= SI_BEFOREDATE;
}
if (ArgV[ARG_MinSize])
SelectInfo.si_MinSize = *(ULONG *) ArgV[ARG_MinSize];
if (ArgV[ARG_MaxSize])
SelectInfo.si_MaxSize = *(ULONG *) ArgV[ARG_MaxSize];
if (ArgV[ARG_PosProtect]) {
SelectInfo.si_Flags |= SI_POSPROTECTION;
SelectInfo.si_PosProtect = ProtectBit(ArgV[ARG_PosProtect]);
}
if (ArgV[ARG_NegProtect]) {
SelectInfo.si_Flags |= SI_NEGPROTECTION;
SelectInfo.si_NegProtect = ProtectBit(ArgV[ARG_NegProtect]);
}
if (ArgV[ARG_Type] && WhatIsBase) {
char IDType[100];
UBYTE NumFT = 0;
char *c, *i;
for (c = ArgV[ARG_Type]; *c && NumFT < MAX_FTS && rc == 0;) {
switch (*c) {
case NOTFileType: // ~
SelectInfo.si_FileTypes[NumFT].fs_Flags |= FTSF_EXCLUDETYPE;
break;
case WITHSubTypes: // #
SelectInfo.si_FileTypes[NumFT].fs_Flags |= FTSF_WITHSUBTYPES;
break;
default:
i = IDType;
while (*c && *c != ',' && i < IDType+100-1)
*i++ = *c++; // copy until ',' or end of string
*i = '\0'; // nul terminate the string
if (SelectInfo.si_FileTypes[NumFT].fs_Flags & FTSF_EXCLUDETYPE)
SelectInfo.si_Flags |= SI_NEGFILETYPE;
else
SelectInfo.si_Flags |= SI_POSFILETYPE;
SelectInfo.si_FileTypes[NumFT].fs_FileType = GetIDType(IDType);
if (TYPE_UNKNOWNIDSTRING == SelectInfo.si_FileTypes[NumFT].fs_FileType) {
Printf("Unknown FileType: %s\n", IDType);
rc = 21; // Hack to prevent PrintFault('no memory')
}
NumFT++;
}
if (*c)
c++;
}
SelectInfo.si_NumFts = NumFT;
}
if (ArgV[ARG_ALL])
SelectInfo.si_Flags |= SI_AFFECT_SUBDIRS;
Opt.Async = (BOOL) ArgV[ARG_ASYNC];
Opt.ReadSize = (ArgV[ARG_READSIZE]) ? *(LONG *) ArgV[ARG_READSIZE] : 488;
Opt.Deep = (ArgV[ARG_DEEPWHATIS]) ? *(LONG *) ArgV[ARG_DEEPWHATIS] : LIGHTTYPE;
if (ArgV[ARG_SHOWBYTES]) {
Opt.Showbytes = (UBYTE) (*(LONG *) ArgV[ARG_SHOWBYTES]);
Opt.Deep = DEEPTYPE;
}
Opt.ShowFileType = (BOOL) ArgV[ARG_SHOWFILETYPE];
Opt.FileTypeVar = (STRPTR) ArgV[ARG_FileTypeVar];
Opt.FullPathArgs = (BOOL) ArgV[ARG_FullPathArgs];
Opt.Verbose = (BOOL) ArgV[ARG_Verbose];
if (rc == 0 && !(Buffer = AllocVec(MAX_PATHLEN, MEMF_ANY)))
rc = RETURN_FAIL;
if (rc == 0 && !(StartPath = AllocVec(MAX_PATHLEN, MEMF_ANY)))
rc = RETURN_FAIL;
if (rc == 0 && !(fib = AllocVec(sizeof(struct FileInfoBlock), MEMF_ANY)))
rc = RETURN_FAIL;
if (rc == 0 && (FileData = AllocVec(Opt.ReadSize + 1, MEMF_ANY))) {
struct AnchorPath *AP;
if (AP = AllocVec(sizeof(struct AnchorPath) + MAX_PATHLEN, MEMF_ANY)) {
LONG IsWild;
STRPTR Elmt;
UBYTE i;
if (Opt.FullPathArgs)
NameFromLock(((struct Process *)SysBase->ThisTask)->pr_CurrentDir, StartPath, MAX_PATHLEN);
else
StartPath[0] = '\0';
for (i = 0; rc == 0 && (Elmt = ((char **) ArgV[ARG_Template])[i]); i++) {
memset(AP, 0, sizeof(struct AnchorPath) + MAX_PATHLEN);
AP->ap_BreakBits = SIGBREAKF_CTRL_C; /* Break on these bits */
AP->ap_Strlen = MAX_PATHLEN;
/*
* For wildcard matching with ALL flag set, two situations are handled differently
* 1. foo#?/bar
* 2. foobar#?
* In the first case, a standard MatchFirst()/MatchNext() is used.
* For the second one, if 'ALL' option is on, the pattern is replaced with "#?"
* so that all directories are parsed, and then files filtered out by the more
* powerfull function Match()
*/
IsWild = ParsePatternNoCase(Elmt, Buffer, MAX_PATHLEN);
if (ArgV[ARG_ALL] && IsWild == 1 && FilePart(Elmt) == Elmt) {
SelectInfo.si_Flags |= SI_NAME;
strcpy(SelectInfo.si_PatTok, Buffer);
rc = ProcessEntryPattern(AP, &SelectInfo, &Opt, StartPath, "#?", FileData, ArgV[ARG_CMD]);
}
else {
BPTR L;
switch (IsWild) {
case 1:
/*
* Pattern
* Dir1/Dir2/Pattern
* Vol:Dir1/Dir2/Pattern
*/
rc = ProcessEntryPattern(AP, &SelectInfo, &Opt, StartPath, Elmt, FileData, ArgV[ARG_CMD]);
break;
case 0:
if (L = Lock(Elmt, SHARED_LOCK)) {
long ok;
ok = Examine(L, fib);
UnLock(L); // UnLock so that command can open file for writing
if (ok) {
if (ArgV[ARG_ALL] && fib->fib_DirEntryType >= 0) { // This is a dir
strcpy(Buffer, Elmt);
AddPart(Buffer, "#?", MAX_PATHLEN);
rc = ProcessEntryPattern(AP, &SelectInfo, &Opt, StartPath, Buffer, FileData, ArgV[ARG_CMD]);
}
else
rc = ProcessEntry(&SelectInfo, fib, StartPath, Elmt, FileData, &Opt, ArgV[ARG_CMD]);
}
else {
PrintFault(IoErr(), Elmt);
rc = RETURN_FAIL;
}
}
else if (ArgV[ARG_CMD]) // Arg does not exists, allow: For 1 2 3 DO Echo %%
rc = ExecuteCmd(ArgV[ARG_CMD], StartPath, Elmt, &Opt);
else
rc = RETURN_WARN;
break;
default:
PrintFault(IoErr(), Elmt);
rc = RETURN_FAIL;
}
}
}
FreeVec(AP);
}
FreeVec(FileData);
}
else if (rc == 21)
rc = RETURN_FAIL;
else
PrintFault(ERROR_NO_FREE_STORE, "For");
if (fib)
FreeVec(fib);
if (Buffer)
FreeVec(Buffer);
if (StartPath)
FreeVec(StartPath);
if (WhatIsBase)
CloseLibrary(WhatIsBase);
return rc;
}